package org.zxp.thread.threadlocal;

public class ThreadLocalTest {
    ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> {
        return 0;
    });

    /**
     * 虽然三个线程都用到了同一个threadLocalTest对象的threadLocal成员变量
     * 但是在threadLocal的set get方法源码中却是根据currentThread来获取的map，也就是说他是按照线程级别去绑定对应的map
     * 所以三个线程执行的add方法并没有相互影响
     */
    public void add() {
        threadLocal.set(threadLocal.get() + 1);
    }

    public Integer get() {
        return threadLocal.get();
    }

    public static void main(String[] args) {
//		//使用同一个threadlocal，也不会串，每个线程都能get set自己的数据
//		ThreadLocalTest threadLocalTest = new ThreadLocalTest();
//		for (int i = 0; i < 3; i++) {
//			new Thread(() -> {
//				for (int j = 0; j < 2; j++) {
//					threadLocalTest.add();
//				}
//				System.out.println(Thread.currentThread().getName() + "计算结果：" + threadLocalTest.get());
//			},"thread-"+i).start();
//		}
//		//使用不同的threadlocal
//		for (int i = 0; i < 3; i++) {
//			ThreadLocal<Integer> threadLocal2 = ThreadLocal.withInitial(() -> {
//				return 0;
//			});
//			new Thread(() -> {
//				for (int j = 0; j < 2; j++) {
//					threadLocal2.set(threadLocal2.get()+1);
//				}
//				System.out.println(Thread.currentThread().getName() + "计算结果：" + threadLocal2.get());
//			},"thread-"+i).start();
//		}

        //使用同一个threadlocal，为什么也可以每个线程互不影响？虽然threadlocal是同一个，
        // 但是他们对应的Entry数组不是同一个
        ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
        new Thread(() -> {
            threadLocal.set(1);
            try {Thread.sleep(500L); } catch (InterruptedException e) {}
            System.out.println(Thread.currentThread().getName()+"  "+threadLocal.get());
        }).start();
        System.out.println(Thread.currentThread().getName()+"  "+threadLocal.get());//null
        new Thread(() -> {
            threadLocal.set(2);
            try {Thread.sleep(500L); } catch (InterruptedException e) {}
            System.out.println(Thread.currentThread().getName()+"  "+threadLocal.get());
        }).start();
        threadLocal.remove();
    }
}